package org.example.JVM.ASM.UseASM;


import org.example.JVM.ByteCode.Util.ByteCodeUtils;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.io.IOException;

import static org.objectweb.asm.Opcodes.*;

/**
 * @description:
 * @author: farprt
 * @create: 2022-11-17 19:14
 **/
public class UseAsmOverrideMethod {

    public static void main(String[] args) throws IOException {
        String subClassName = BaseClass.class.getName().replace("Base", "Sub");
        ClassWriter classWriter = new ClassWriter(0);

        classWriter.visit(Opcodes.V1_8
                , ACC_PUBLIC
                , subClassName.replace(".", "/")
                , null
                , Type.getInternalName(BaseClass.class)
                , null);

        MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC
                , "sayHello"
                , "()V"
                , null
                , null);

        //调用父类方法
        methodVisitor.visitVarInsn(ALOAD, 0);
        methodVisitor.visitMethodInsn(INVOKESPECIAL
                , Type.getInternalName(BaseClass.class)
                , "sayHello"
                , "()V",
                false);

        methodVisitor.visitFieldInsn(GETSTATIC
                , Type.getInternalName(System.class)
                , "out"
                , Type.getDescriptor(System.out.getClass()));

        methodVisitor.visitLdcInsn("SubClass sayHello");

        methodVisitor.visitAnnotation("Override", false);

        methodVisitor.visitMethodInsn(INVOKEVIRTUAL
                , Type.getInternalName(System.out.getClass())
                , "println"
                , "(Ljava/lang/String;)V"
                , false);
        methodVisitor.visitInsn(RETURN);
        methodVisitor.visitMaxs(2, 1);
        byte[] byteCode = classWriter.toByteArray();
        ByteCodeUtils.saveToFile(subClassName, byteCode);

    }
}